import { ENUM_TON_NOTCH, ExtSkuTpl, StockNode, TimeFilter, TonSku, TonSkuJoinLs, TonSkuJoinLsKey, WithStockTotal } from "qqlx-core";

import { toNumber, toString } from "@lib/com.verify";
import { toDivideSafe, toMultiplySafe } from "@lib/com.amount";

import { getIntroUpdater } from "@/data-base";
import { doNotchMerge } from "@/river/data-river-ton-tpl";
import { doBitsToDecimal, doDecimalToBits } from "@lib/com.binary";
import { getTimeFilter } from "@lib/com.search.condition";

export function getSkuTplUpdater(tpl: ExtSkuTpl) {
  return {
    ...getIntroUpdater(tpl),
    norm: toString(tpl.norm).replace(/\s+/g, ""),
    count: toNumber(tpl.count),
    unit: toString(tpl.unit).replace(/\s+/g, ""),
    price: toNumber(tpl.price),
    tax: toNumber(tpl.tax),
  };
}

/** 库存名称设置的时间范围 */
export function getStockNodeTime(entity: StockNode): TimeFilter {
  const timeStart = toNumber(entity.timeStart);
  const timeEnd = toNumber(entity.timeEnd);

  const timeFilter = getTimeFilter();
  timeFilter.startTime = Math.min(timeStart, timeEnd).toString();
  timeFilter.endTime = Math.max(timeStart, timeEnd).toString();
  return timeFilter;
}

/** 帮助商品，补充库存信息 */
export function formatTonSkuIv<T>(skuLs: (T & TonSku)[]): (T & TonSku & WithStockTotal)[] {
  return skuLs.map((sku) => {
    const { map } = doNotchMerge([]);

    return {
      ...sku,
      //
      withInOutCountTotal: "0",
      withInOutTonTotal: map.get(ENUM_TON_NOTCH.IN_OUT)?.total || "0",
      //
      withNotInCountTotal: "0",
      withNotInTonTotal: map.get(ENUM_TON_NOTCH.NOT_IN)?.total || "0",
      //
      withNotProcessCountTotal: "0",
      withNotProcessTonTotal: map.get(ENUM_TON_NOTCH.NOT_PROCESS)?.total || "0",
      //
      withNotOutCountTotal: "0",
      withNotOutTonTotal: map.get(ENUM_TON_NOTCH.NOT_OUT)?.total || "0",
    };
  });
}

/** 统计客户输入的多件商品，最后得到（元、吨）的商品 */
export function getSkuCalcuClient(skuLs: TonSku[]) {
  const data = { cent: 0, kg: 0, count: 0 };
  skuLs.map((sku) => {
    const _count = toDivideSafe(sku.count, 1000, 3);
    data.count += _count;

    const _kg = sku.isTonAble ? toMultiplySafe(sku.ton, 1000) : 0; // 千克（整数）
    data.kg += _kg; // 千克（整数）

    const _price = toMultiplySafe(sku.price, 100); // 分（整数）
    if (sku.isTonAble) {
      data.cent += toDivideSafe(_price * _kg, 1000, 0);
    } else {
      const _count = toMultiplySafe(sku.count, 1000);
      data.cent += toDivideSafe(_price * _count, 1000, 0); // 还原数量count并截断成金额分
    }
  });

  return {
    count: data.count, // 数量（三位小数）

    kg: data.kg, // 千克（整数）
    dun: toDivideSafe(data.kg, 1000, 3), // 吨（三位小数）

    cent: data.cent, // 分（整数）
    yuan: toDivideSafe(data.cent, 100, 2), // 元（两位小数）
  };
}

/** 统计数据库寻得的多件商品，最后得到（元、吨）的商品 */
export function getSkuCalcuServer(skuLs: TonSku[]) {
  const data = { cent: 0, kg: 0, count: 0 };
  skuLs.map((sku) => {
    data.count += toDivideSafe(sku.count, 1000, 3);

    const _kg = sku.isTonAble ? toMultiplySafe(sku.ton, 1) : 0; // 千克（整数）
    data.kg += _kg;

    const _price = toMultiplySafe(sku.price, 1); // 分（整数）
    if (sku.isTonAble) {
      data.cent += toDivideSafe(_price * _kg, 1000, 0);
    } else {
      data.cent += toDivideSafe(_price * sku.count, 1000, 0); // 还原数量count并截断金额分
    }
  });

  return {
    count: data.count, // 数量（三位小数）

    kg: data.kg, // 千克（整数）
    dun: toDivideSafe(data.kg, 1000, 3), // 吨（三位小数）

    cent: data.cent, // 分（整数）
    yuan: toDivideSafe(data.cent, 100, 2), // 元（两位小数）
  };
}

/** 将商品的查询对象，转换成二进制字符串 */
export function getTonSkuJoinDecimal(option: Partial<Record<TonSkuJoinLsKey, true>>) {
  const value = doDecimalToBits(0, TonSkuJoinLs.length);
  const bits = value.bits.split("");

  for (const key in option) {
    const index = TonSkuJoinLs.findIndex((k) => k === key);
    if (index > -1) bits[index] = "1";
  }
  return doBitsToDecimal(bits.join("")).decimal;
}

/** 将二进制字符串，转换成商品的查询对象 */
export function getTonSkuJoinRecord(decimal: number) {
  const value = doDecimalToBits(decimal, TonSkuJoinLs.length);
  const bits = value.bits.split("");

  const record: Partial<Record<TonSkuJoinLsKey, true>> = {};
  for (const index in bits) {
    const key = TonSkuJoinLs[index];
    if (bits[index] === "1") record[key] = true;
  }
  return record;
}
